import { showMessage } from '@/components/antd-comp/message'
import ThemeBtn from '@/components/antd-comp/theme-btn'
import { WorkflowRunningStatus } from '@/components/workflow/types'
import { useWorkFlowStore } from '@/store/workflowStore'
import cn from '@/util/classnames'
import { RiCloseLine } from '@remixicon/react'
import { Form, Input, InputNumber, Switch } from 'antd'
import { Rule } from 'antd/es/form'
import { memo, useEffect, useRef, useState } from 'react'
import { getWorkFlowDetailApi } from '../API'
import { graphToRunGraph, inputToRunInput } from '../compatible'
import { useAutoSave } from '../hooks/use-save'
import { findStartVariables, getUserInputsInfo } from '../utils'
import './style.less'

const RunPanel = ({ node, changeBottomPanelStatus, closePanel = (status: boolean) => {} }: any) => {
  const panelWidth = 500
  const {
    flow,
    flowVariables,
    running,
    setRunning,
    updateSingleRunningInfo,
    clearRunInfo,
    setErrorInfo,
    updateRunningToError,
    setRunTime
  } = useWorkFlowStore()
  const { getMergedGraph } = useAutoSave()

  const [form] = Form.useForm()
  const startVariables = findStartVariables(flowVariables)
  // console.log('RunPanel: flow, flowVariables, startVariables', flow, flowVariables, startVariables)

  const wsRef = useRef(null)
  const [localRunning, setLocalRunning] = useState(false)
  const userInput = useRef(null)

  useEffect(() => {
    return () => {
      if (wsRef.current) {
        wsRef.current.close()
      }
      userInput.current = null
    }
  }, [])

  /**
   * 处理用户输入
   */
  function handleUserInput(data: any) {
    wsRef.current.send(JSON.stringify(userInput.current))
    const inputs = getUserInputsInfo(userInput.current?.data)
    updateSingleRunningInfo(data.message.node_id, WorkflowRunningStatus.Running, { inputs })
  }

  const errInfo = useRef(null)
  /**
   * 处理接口响应
   */
  function handleNodeRun(data: any) {
    const nodeId = data.message?.node_id
    if (data.message?.reason) {
      const err = `节点${data.message.name}运行失败：${data.message.reason}`
      errInfo.current = err
      updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Failed)
      setErrorInfo(err)
      changeBottomPanelStatus(true)
      return
    }
    if (data.type === 'start') {
      const inputs = getUserInputsInfo(userInput.current?.data)
      updateSingleRunningInfo(data.message.node_id, WorkflowRunningStatus.Running, {
        inputs,
        startTime: new Date().valueOf()
      })
    } else if (data.type === 'end') {
      updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, { endTime: new Date().valueOf() })
      if (nodeId.startsWith('llm_')) {
        updateLlmNode(nodeId, data.message.log_data)
      } else if (nodeId.startsWith('end_')) {
        updateEndNode(nodeId, data.message.log_data)
      }
    }
  }

  function updateLlmNode(nodeId: string, logData: any) {
    const inputKeys = flowVariables[nodeId]?.inputList?.map(item => item.variable) || []
    const inputValues = logData.user_prompt?.[0]?.split('\n') || []
    const minArrayLength = Math.min(inputKeys.length, inputValues.length)
    // const inputs = Array.from({ length: minArrayLength }, (_, index) => ({
    //   variable: inputKeys[index],
    //   value: inputValues[index]
    // }))
    const inputs = Array.from({ length: minArrayLength }, (_, index) =>
      index < inputValues.length ? inputValues[index] : ''
    )
    // const outputs = objToRunInfoArray(logData.output)
    const outputs = logData?.output?.output
    const systemPrompt = logData.system_prompt?.[0]
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, {
      inputs,
      system_prompt: systemPrompt,
      outputs
    })
  }

  function updateEndNode(nodeId: string, logData: any) {
    const outputs = logData.output_msg
    updateSingleRunningInfo(nodeId, WorkflowRunningStatus.Succeeded, { outputs })
  }

  const updateRunTimer = () => {
    getWorkFlowDetailApi(flow.id).then((res: any) => {
      if (res?.flow?.run_timestamp) {
        setRunTime(res.flow.run_timestamp.replace('T', ' '))
      }
    })
  }

  /**
   * 处理接口异常信息
   * error未包含异常节点的id，暂时先简单处理：
   * 1、error发生时将所有running中的节点设置为运行失败，
   * 2、并主动关闭连接
   * 3、失败原因不单独显示，直接显示一个统一的失败面板
   */
  function handleNodeError(data: any) {
    console.log('handleNodeError: data', data)
    if (wsRef.current) {
      wsRef.current.close()
      wsRef.current = null
    }
    if (!errInfo.current) {
      setErrorInfo(data.message)
      updateRunningToError()
      changeBottomPanelStatus(true)
    }
    setLocalRunning(false)
  }
  const initWorkflow = () => {
    if (wsRef.current) {
      wsRef.current.close()
      wsRef.current = null
    }
    errInfo.current = null

    const isSecureProtocol = window.location.protocol === 'https:'
    const webSocketProtocol = isSecureProtocol ? 'wss' : 'ws'
    const token = localStorage.getItem('ws_token') || ''
    const wsUrl = `${location.host}/api/v1/workflow/chat/${flow.id}?t=${token}`

    return new Promise((resolve, reject) => {
      try {
        const ws = new WebSocket(`${webSocketProtocol}://${wsUrl}`)
        wsRef.current = ws
        ws.onopen = () => {
          console.log('WebSocket connection established!')
          resolve('ok')
        }
        ws.onmessage = event => {
          try {
            const data = JSON.parse(event.data)

            if (data.category === 'user_input') {
              handleUserInput(data)
            } else if (data.category === 'node_run' && data.message?.node_id) {
              handleNodeRun(data)
            } else if (data.category === 'error') {
              handleNodeError(data)
            } else if (data.type === 'close') {
              updateRunTimer()
              setLocalRunning(false)
              wsRef.current.close() // 这里等后端主动断开
            }
          } catch (error) {
            console.error('解析数据异常', error, event.data)
            handleNodeError({
              message: `返回数据异常：${event.data}`
            })
          }
        }
        ws.onclose = event => {
          console.error('链接手动断开 event :>> ', event)
          console.log('ws.onclose event.code ', event.code)
          if (event.code === 1011) {
            handleNodeError({
              code: event.code,
              message: event.reason || '后端未知错误类型'
            })
          } else if (event.code === 4451) {
            handleNodeError({
              code: event.code,
              message: event.reason || '内容不合规，请重新操作'
            })
          }
          wsRef.current = null
          setLocalRunning(false)
        }
        ws.onerror = err => {
          wsRef.current = null
          setLocalRunning(false)
          console.error('链接异常error', err)
        }
      } catch (err) {
        console.error('创建链接异常', err)
        reject(err)
      }
    })
  }
  const showMessageFun = (cont, type = 'warning') => {
    showMessage({
      content: cont,
      type
    })
  }

  const initWsAndRun = async values => {
    const initGraph = graphToRunGraph(flow, getMergedGraph(flow.id))
    console.log('initGraph', flow, getMergedGraph(flow.id), initGraph)
    /* socket */
    await initWorkflow()

    wsRef.current.send(JSON.stringify(initGraph))
    const runInput = inputToRunInput(startVariables.id, values, startVariables.variables)
    userInput.current = runInput

    console.log('graphToRunGraph result', initGraph)
    console.log('inputToRunInput result', runInput)
  }
  /* run运行 */
  const handleRunEvent = () => {
    clearRunInfo()
    changeBottomPanelStatus(false)
    form
      .validateFields()
      .then(async values => {
        console.log('handleRunEvent values', values)
        setRunning(true)
        setLocalRunning(true)
        initWsAndRun(values)
      })
      .catch(err => {
        console.error('err', err)
      })
  }
  const getInitialValues = (startVariables: any) => {
    if (!startVariables || !startVariables.variables) {
      return {}
    }

    return startVariables.variables.reduce((acc: any, item: any) => {
      if (item.type === 'boolean') {
        acc[item.variable] = true // 设置布尔类型的默认值为 true
      }
      return acc
    }, {})
  }
  return (
    <div
      className={cn(
        'custom-run-container',
        'fixed right-[0] top-[57px] h-[calc(100vh-57px)] bg-[#ffffff]',
        'overflow-visible  shadow-lg transition-all'
      )}
      style={{
        width: `${panelWidth}px`
      }}
    >
      <div
        className={cn('h-[100%] overflow-y-auto rounded-2xl transition-all', 'border-[1px] border-transparent')}
        style={{
          width: `${panelWidth}px`
        }}
      >
        <div className="sticky top-0 z-10 cursor-move border-b-[0.5px] border-black/5">
          <div className="flex h-[56px] items-center bg-[#ffffff] px-4 pb-1 pt-1">
            <div className="leading-0 flex w-[320px] px-2 py-[5px]">试运行</div>
            <div
              className="flex shrink-0 items-center justify-end text-gray-500"
              style={{
                width: '148px'
              }}
            >
              <div className="mx-3 h-3.5 w-[1px] bg-[#eaecf0]" />
              <div className="flex h-6 w-6 cursor-pointer items-center justify-center rounded-md hover:bg-black/5">
                <RiCloseLine
                  className="text-text-tertiary h-4 w-4"
                  onClick={() => {
                    closePanel()
                  }}
                />
              </div>
            </div>
          </div>
        </div>
        <div className="m-[16px] mb-[100px]">
          <Form form={form} layout="vertical" initialValues={getInitialValues(startVariables)}>
            {startVariables && startVariables.variables
              ? startVariables.variables.map(item => {
                  let inputNode
                  const rules: Rule[] = [{ required: item.required, message: `${item.variable}不能为空` }]
                  switch (item.type) {
                    case 'integer':
                      inputNode = (
                        <InputNumber
                          name={item.variable}
                          step={1}
                          precision={0}
                          min={-1000000000000}
                          max={1000000000000}
                          placeholder="请输入"
                          style={{ width: '400px' }}
                        />
                      )
                      break
                    case 'number':
                      inputNode = (
                        <InputNumber
                          name={item.variable}
                          min={-1000000000000}
                          max={1000000000000}
                          placeholder="请输入"
                          style={{ width: '400px' }}
                        />
                      )
                      break
                    case 'boolean':
                      inputNode = <Switch defaultChecked />
                      break
                    case 'string':
                    case 'text':
                    default:
                      rules.push({ max: 500, message: `输入不能大于500个字符` })
                      inputNode = (
                        <Input
                          name={item.variable}
                          autoComplete="off"
                          placeholder="请输入"
                          style={{ width: '400px' }}
                        />
                      )
                  }

                  return (
                    <Form.Item
                      key={item.id}
                      name={item.variable}
                      label={`${item.variable}(${item.type})`}
                      required={item.required}
                      rules={rules}
                    >
                      {inputNode}
                    </Form.Item>
                  )
                })
              : '开始节点参数错误'}
          </Form>
        </div>
        <div className="absolute bottom-0 z-10 w-[100%] cursor-move border-t-[0.5px] border-black/5  bg-[#ffffff]">
          <div className="flex h-[56px] items-center justify-center px-4 pb-1 pt-1">
            <ThemeBtn
              loading={running && localRunning && wsRef.current}
              className="w-[100%]"
              onClick={() => handleRunEvent()}
            >
              试运行
            </ThemeBtn>
          </div>
        </div>
      </div>
    </div>
  )
}

export default memo(RunPanel)
